<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite App</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <div id="app"></div>
  <script type="module">
    // 引入three
    import * as THREE from 'three';
    // 引入轨道控制器
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
    // 创建场景
    const scene = new THREE.Scene();
    // 刚改背景
    scene.background = new THREE.Color(0xcccccc);
    // 创建相机
    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 200, 300);
    camera.lookAt(0, 0, 0);
    // 创建一个物体
    const cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0x00ff00 }));
    // 添加物体到场景
    scene.add(cube);
    const radarData = {
      position: {
        x: 0,
        y: 20,
        z: 0
      },
      radius: 240,
      color: '#f005f0',
      opacity: 0.5,
      speed: 300,
      followWidth: 220
    }


    const circleGeometry = new THREE.CircleGeometry(radarData.radius, 1000)
    const rotateMatrix = new THREE.Matrix4().makeRotationX((-Math.PI / 180) * 90)
    circleGeometry.applyMatrix4(rotateMatrix)
    const material = new THREE.MeshBasicMaterial({
      color: radarData.color,
      opacity: radarData.opacity,
      transparent: true
    })

    const radar = new THREE.Mesh(circleGeometry, material)
    radar.updateMatrix()

    scene.add(radar)

    material.onBeforeCompile = (shader) => {
  Object.assign(shader.uniforms, {
    uSpeed: {
      value: radarData.speed
    },
    uRadius: {
      value: radarData.radius
    },
    uTime: {
      value: 0
    },
    uFollowWidth: {
      value: radarData.followWidth
    }
  })

  requestAnimationFrame(function update(time) {
    shader.uniforms.uTime.value = time / 1000
    requestAnimationFrame(update)
  })

  const vertex = `


      varying vec3 vPosition;
      void main() {

        vPosition = position;

    `
  shader.vertexShader = shader.vertexShader.replace('void main() {', vertex)
  const fragment = `


      uniform float uRadius;     
      uniform float uTime;            
      uniform float uSpeed; 
      uniform float uFollowWidth; 
      varying vec3 vPosition;
     

      float calcAngle(vec3 oFrag){

        float fragAngle;

        const vec3 ox = vec3(1,0,0);

        float dianji = oFrag.x * ox.x + oFrag.z*ox.z;

        float oFrag_length = length(oFrag); // length是内置函数
        float ox_length = length(ox); // length是内置函数

        float yuxian = dianji / (oFrag_length * ox_length);


        fragAngle = acos(yuxian);
        fragAngle = degrees(fragAngle);


        if(oFrag.z > 0.0) {
          fragAngle = -fragAngle + 360.0;
        }


        float scanAngle = uTime * uSpeed - floor(uTime * uSpeed / 360.0) * 360.0;

        float angle = scanAngle - fragAngle;

        if(angle < 0.0){
          angle = angle + 360.0;
        }


        return angle;
      }

      void main() {
  
    `

  const fragementColor = `
      #include <opaque_fragment>
      

      // length内置函数，取向量的长度
      if(length(vPosition) == 0.0 || length(vPosition) > uRadius-2.0){
        gl_FragColor = vec4( outgoingLight, diffuseColor.a );

      } else {

        float angle = calcAngle(vPosition);
        if(angle < uFollowWidth){
          // 尾焰区域
          float opacity =  1.0 - angle / uFollowWidth; 
          gl_FragColor = vec4( outgoingLight, diffuseColor.a * opacity );  

        } else {
          // 其他位置的像素均为透明
          gl_FragColor = vec4( outgoingLight, 0.0 ); 

        }

      }
      
    `
  shader.fragmentShader = shader.fragmentShader.replace('void main() {', fragment)

  shader.fragmentShader = shader.fragmentShader.replace('#include <opaque_fragment>', fragementColor)

}


    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    // 添加渲染器到页面
    document.body.appendChild(renderer.domElement);
    // 设置渲染器大小
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 渲染器渲染场景
    renderer.render(scene, camera);

    const controls = new OrbitControls(camera, renderer.domElement);

    controls.enableDamping = true;

    function animate() {
      requestAnimationFrame(animate);
      // cube.rotation.x+=0.01;
      // cube.rotation.y+=0.01;

      controls.update();


      renderer.render(scene, camera);
    }
    animate();

    async function createBeijingMap() {
        const group = new THREE.Group();
        
        // 创建发光材质
        const glowMaterial = new THREE.LineBasicMaterial({
            color: 0x00ffff,
            transparent: true,
            opacity: 0.8,
            linewidth: 2
        });

        try {
            // 加载北京地图的 GeoJSON 数据
            const response = await fetch('https://geo.datav.aliyun.com/areas_v3/bound/110000_full.json');
            const geoJson = await response.json();
            
            // 遍历所有的地区边界
            geoJson.features.forEach(feature => {
                feature.geometry.coordinates.forEach(coordinates => {
                    const points = [];
                    // 将经纬度坐标转换为三维坐标
                    coordinates[0].forEach(coord => {
                        // 增加缩放系数
                        const scale = 100;
                        points.push(new THREE.Vector3(
                            (coord[0] - 116.4) * scale,
                            0,
                            -(coord[1] - 39.9) * scale  // 注意这里加了负号
                        ));
                    });
                    
                    // 创建边界线
                    const geometry = new THREE.BufferGeometry().setFromPoints(points);
                    const line = new THREE.Line(geometry, glowMaterial);
                    group.add(line);
                });
            });

            // 将整个组居中
            const box = new THREE.Box3().setFromObject(group);
            const center = box.getCenter(new THREE.Vector3());
            group.position.sub(center);

        } catch (error) {
            console.error('加载地图数据失败:', error);
        }
        
        return group;
    }

    // 修改调用方式并添加调试信息
    createBeijingMap().then(beijingMap => {
        scene.add(beijingMap);
        console.log('地图已添加到场景');
    }).catch(error => {
        console.error('创建地图失败:', error);
    });

    // 添加网格辅助线（帮助调试）
    const gridHelper = new THREE.GridHelper(1000, 100);
    scene.add(gridHelper);

  </script>
</body>

</html>

